package zend.view.helper;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

public class Doctype extends TagSupport {

	private static final long serialVersionUID = 1L;

	/**
	 * DocType constants
	 */
	static String XHTML11 = "XHTML11";
	static String XHTML1_STRICT = "XHTML1_STRICT";
	static String XHTML1_TRANSITIONAL = "XHTML1_TRANSITIONAL";
	static String XHTML1_FRAMESET = "XHTML1_FRAMESET";
	static String XHTML1_RDFA = "XHTML1_RDFA";
	static String XHTML1_RDFA11 = "XHTML1_RDFA11";
	static String XHTML_BASIC1 = "XHTML_BASIC1";
	static String XHTML5 = "XHTML5";
	static String HTML4_STRICT = "HTML4_STRICT";
	static String HTML4_LOOSE = "HTML4_LOOSE";
	static String HTML4_FRAMESET = "HTML4_FRAMESET";
	static String HTML5 = "HTML5";
	static String CUSTOM_XHTML = "CUSTOM_XHTML";
	static String CUSTOM = "CUSTOM";

	/**
	 * Default DocType
	 *
	 * @var string
	 */
	protected String _defaultDoctype = HTML4_LOOSE;

	/**
	 * Registry containing current doctype and mappings
	 * 
	 * @deprecated no longer needed
	 * @var ArrayObject
	 * 
	 */
	// protected Map<String, Object> _registry;

	/**
	 * Registry key in which helper is stored TODO:comentado porque no se usa
	 * 
	 * @deprecated no longer needed
	 * @var string
	 */
	// protected String _regKey = "Zend_View_Helper_Doctype";

	/**
	 * Registry key DocType
	 */
	protected String doctype;

	/**
	 * Constructor
	 *
	 * Map constants to doctype strings, and set default doctype
	 *
	 * @return void
	 */
	public Doctype() {
		super();

		Map<String, String> doctypeMap = new HashMap<String, String>();
		doctypeMap
				.put(XHTML11,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">");
		doctypeMap
				.put(XHTML1_STRICT,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
		doctypeMap
				.put(XHTML1_TRANSITIONAL,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
		doctypeMap
				.put(XHTML1_FRAMESET,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">");
		doctypeMap
				.put(XHTML1_RDFA,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.0//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd\">");
		doctypeMap
				.put(XHTML1_RDFA11,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.1//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd\">");
		doctypeMap
				.put(XHTML_BASIC1,
						"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML Basic 1.0//EN\" \"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd\">");
		doctypeMap.put(XHTML5, "<!DOCTYPE html>");
		doctypeMap
				.put(HTML4_STRICT,
						"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">");
		doctypeMap
				.put(HTML4_LOOSE,
						"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
		doctypeMap
				.put(HTML4_FRAMESET,
						"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">");
		doctypeMap.put(HTML5, "<!DOCTYPE html>");

		setValue("doctypes", doctypeMap);

		setDoctype(_defaultDoctype);
	}

	/**
	 * Set or retrieve doctype
	 *
	 * @param String
	 *            doctype
	 * @return int Zend_View_Helper_Doctype
	 */
	public int doStartTag() throws JspException {
		if (getDoctype().equalsIgnoreCase(XHTML11)
				|| getDoctype().equalsIgnoreCase(XHTML1_STRICT)
				|| getDoctype().equalsIgnoreCase(XHTML1_TRANSITIONAL)
				|| getDoctype().equalsIgnoreCase(XHTML1_FRAMESET)
				|| getDoctype().equalsIgnoreCase(XHTML_BASIC1)
				|| getDoctype().equalsIgnoreCase(XHTML1_RDFA)
				|| getDoctype().equalsIgnoreCase(XHTML1_RDFA11)
				|| getDoctype().equalsIgnoreCase(XHTML5)
				|| getDoctype().equalsIgnoreCase(HTML4_STRICT)
				|| getDoctype().equalsIgnoreCase(HTML4_LOOSE)
				|| getDoctype().equalsIgnoreCase(HTML4_FRAMESET)
				|| getDoctype().equalsIgnoreCase(HTML5)) {
			setDoctype(getDoctype());
		} else {
			throw new JspException("The specified doctype is malformed");
		}

		try {
			JspWriter out = pageContext.getOut();
			out.println(this);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return super.doStartTag();
	}

	/**
	 * Set doctype
	 *
	 * @param string
	 *            $doctype
	 * @return Zend_View_Helper_Doctype
	 */
	public void setDoctype(String doctype) {
		setValue("doctype", doctype);
	}

	/**
	 * Retrieve doctype
	 *
	 * @return string
	 */
	public String getDoctype() {
		return (String) getValue("doctype");
	}

	/**
	 * Get doctype => string mappings
	 *
	 * @return array
	 */
	public Object getDoctypes() {
		return getValue("doctypes");
	}

	/**
	 * Is doctype XHTML?
	 *
	 * @return boolean
	 */
	public boolean isXhtml() {
		return (this.getDoctype().equalsIgnoreCase("xhtml") ? true : false);
	}

	/**
	 * Is doctype strict?
	 *
	 * @return boolean
	 */
	public boolean isStrict() {
		if (this.getDoctype().equalsIgnoreCase(XHTML1_STRICT)
				|| this.getDoctype().equalsIgnoreCase(XHTML11)
				|| this.getDoctype().equalsIgnoreCase(HTML4_STRICT)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Is doctype HTML5? (HeadMeta uses this for validation)
	 *
	 * @return booleean
	 */
	public boolean isHtml5() {
		return (this.getDoctype().equalsIgnoreCase("<!DOCTYPE html>") ? true
				: false);
	}

	/**
	 * Is doctype RDFa?
	 *
	 * @return booleean
	 */
	public boolean isRdfa() {
		return (this.getDoctype().equalsIgnoreCase("rdfa") ? true : false);
	}

	/**
	 * String representation of doctype
	 *
	 * @return string
	 */
	@SuppressWarnings("unchecked")
	@Override
	public String toString() {
		Map<String, String> $doctypes = (Map<String, String>) this
				.getDoctypes();
		return $doctypes.get(this.getDoctype());
	}

}
